package com.example.a2032.Utils;

import android.content.Context;
import android.util.Log;

import com.amap.api.location.AMapLocationClient;
import com.example.a2032.MyApp;
import com.example.a2032.constant.DeviceConst;
import com.example.a2032.db.DataDbHelper;
import com.example.a2032.db.dao.DeviceInfoDao;
import com.example.a2032.listener.DeviceDataListener;
import com.example.a2032.entity.EcgMeasureResult;
import com.example.a2032.entity.PPGMeasureData;
import com.example.a2032.entity.RealTimeStepData;
import com.example.a2032.entity.SleepData;
import com.example.a2032.entity.WatchUserInfo;
import com.example.a2032.net.jstylenet.NetSendUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

public class ResolveUtil {
    public static String byte2Hex(byte[] data) {

        if (data != null && data.length > 0) {
            StringBuilder sb = new StringBuilder(data.length);
            for (byte tmp : data) {
                sb.append(String.format("%02X ", tmp));
            }
            return sb.toString();
        }
        return "no data";
    }


    public static byte timeString2Hex(int value) {
        String data = value + "";
        Integer m = Integer.parseInt(data, 16);
        return (byte) m.intValue();
    }

    private static final String TAG = "ResolveUtil";

//    public static void resolveData(byte[] value, DeviceDataListener deviceDataListener) {
//        if (!checkHead(value)) return;
//        int dataLength = value.length;
//        int index = 0;
//        while (index < dataLength) {
//            Log.i(TAG, "resolveData: " + index);
//            if (checkHead(value, index)) {
//                int bleLength = getSingleValue(value[index + 4]);
//                byte[] bleValue = new byte[bleLength];
//                System.arraycopy(value, index + 5, bleValue, 0, bleLength);
//                postData(bleValue, deviceDataListener);
//                index = index + bleLength + 6;
//            } else {
//                index++;
//            }
//        }
//
//    }

    public static void postData(byte[] bleValue, DeviceDataListener deviceDataListener) {
        switch (bleValue[0]) {
            case DeviceConst.CMD_GetTemp:
                deviceDataListener.TempData(getTempValue(bleValue));
                break;
            case DeviceConst
                    .CMD_Get_Address:

                deviceDataListener.DeviceAddress(getDeviceAddress(bleValue));
                break;
            case DeviceConst.CMD_Get_Version:
                deviceDataListener.DeviceVersion(getDeviceVersion(bleValue));
                break;
            case DeviceConst.CMD_GET_TIME:
                deviceDataListener.DeviceTime(getDeviceTime(bleValue));
                break;
            case DeviceConst.CMD_GET_USERINFO:
                deviceDataListener.DeviceUserInfo(getUserInfo(bleValue));
                break;
            case DeviceConst.CMD_Enable_Activity:
                deviceDataListener.RealTimeData(getRealTimeData(bleValue));
                break;
            case DeviceConst.CMD_DeviceSend:
                deviceDataListener.PPGMeasureData(getPPGMeasureData(bleValue));
                break;
            case DeviceConst.CMD_EnterEcg:
                deviceDataListener.EcgMeasureData(getEcgData(bleValue));
                break;
            case DeviceConst.CMD_Get_SleepData:
                deviceDataListener.SleepData(getSleepData(bleValue), bleValue.length < 7);
                break;
            case DeviceConst.CMD_DisableSerialPort:
               // SerialPortUtil.getInstance().setOpenSerialPort(false);
                break;
        }
    }

    public static boolean checkHead(byte[] value) {
        return checkHead(value, 0);
    }

    public static boolean checkHead(byte[] value, int index) {
        if (value.length <= index + 3) return false;
        return value[index] == (byte) 0x4a && value[index + 1] == (byte) 0x43 && value[index + 2] == (byte) 0xaa && value[index + 3] == (byte) 0xaa;
    }

    public static boolean isSleepEnd(byte[] value) {
        int index = value.length - 10;
        return value[index] == (byte) 0x4a && value[index + 1] == (byte) 0x43 && value[index + 2] == (byte) 0xaa && value[index + 3] == (byte) 0xaa && value[index + 4] == DeviceConst.CMD_Get_SleepData && value[index + 5] == (byte) 0xff;
    }

    /**
     * 设备mac地址
     *
     * @param value
     * @return
     */
    public static String getDeviceAddress(byte[] value) {
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i < 7; i++) {
            sb.append(String.format("%02X", value[i])).append(":");
        }
        String address = sb.toString();
        String mac = address.substring(0, address.lastIndexOf(":"));
        Context context = MyApp.getInstance();
        DeviceInfoDao deviceInfoDao= DataDbHelper.getInstance(context).getDeviceInfoDao();
        if(deviceInfoDao==null){
            WebSocketUtils.getInstance().sendMsg(NetSendUtils.registerDevice(Utils.getIMEI(context), mac, Utils.getPhone(context)));
        }
        return mac;
    }

    /**
     * 设备版本号
     *
     * @param value
     * @return
     */
    public static String getDeviceVersion(byte[] value) {
        //    String version = "";
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 1; i < 5; i++) {
            stringBuffer.append((char) getSingleValue(value[i])).append(i == 4 ? "" : ".");
        }
        return stringBuffer.toString();
    }

    public static Calendar getDeviceTime(byte[] value) {
        Calendar calendar = Calendar.getInstance();
        int year = bcd2String(value[1]);
        int month = bcd2String(value[2]);
        int day = bcd2String(value[3]);
        int hour = bcd2String(value[4]);
        int minute = bcd2String(value[5]);
        int second = bcd2String(value[6]);
        calendar.set(Calendar.YEAR, year + 2000);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, second);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Log.i(TAG, "getDeviceTime: " + format.format(calendar.getTime()));


        return calendar;
    }

    public static WatchUserInfo getUserInfo(byte[] value) {
        WatchUserInfo watchUserInfo = new WatchUserInfo();
        int gender = getSingleValue(value[1]);
        int age = getSingleValue(value[2]);
        int height = getSingleValue(value[3]);
        int weight = getSingleValue(value[4]);
        int stride = getSingleValue(value[5]);
        String deviceId = "";
        for (int i = 6; i < 12; i++) {
            if (value[i] == 0)
                continue;
            deviceId += (char) getValue(value[i], 0);
        }
        watchUserInfo.setAge(age);
        watchUserInfo.setGender(gender);
        watchUserInfo.setHeight(height);
        watchUserInfo.setWeight(weight);
        watchUserInfo.setStrideLength(stride);
        watchUserInfo.setId(deviceId);
        return watchUserInfo;
    }

    /**
     * 实时计步信息
     *
     * @param value
     * @return
     */
    public static RealTimeStepData getRealTimeData(byte[] value) {
        float stepLength = 0.7f;
        int step = getRangeValue(value, 1, 4);
        float cal = getRangeValue(value, 5, 4);
        //默认步长70cm，距离步长*距离
        float distance = stepLength * step;
        //   int time =getRangeValue(value,13,4);
        //   int exerciseTime = getRangeValue(value,17,4);
        int heartRate = getValue(value[21], 0);
        //int temp = getRangeValue(value, 22,2);
        RealTimeStepData timeStepData = new RealTimeStepData();
        timeStepData.setCal(getBigDecimalData(cal / 100, 2));
        timeStepData.setDistance(getBigDecimalData(distance / 1000, 2));
        //  timeStepData.setTempValue(getBigDecimalData(temp * 0.1f,1));
        timeStepData.setStep(step);
        timeStepData.setHeartRate(heartRate);
        //  timeStepData.setTime(time / 60);
        //        // timeStepData.setExerciseTime(exerciseTime);
        Log.i(TAG, "getRealTimeData: " + timeStepData.toString());
        return timeStepData;
    }

    public static PPGMeasureData getPPGMeasureData(byte[] value) {
        PPGMeasureData ppgMeasureData = new PPGMeasureData();
        int dataType = getSingleValue(value[1]);
        int wearStatus = getSingleValue(value[2]);
        int heartRate = getSingleValue(value[3]);
        int measureValue = getSingleValue(value[4]);
        ppgMeasureData.setDataType(dataType);
        ppgMeasureData.setWearStatus(wearStatus);
        ppgMeasureData.setHeartRate(heartRate);
        ppgMeasureData.setMeasureValue(measureValue);
        if (dataType != PPGMeasureData.MeasureData_ECGHR) {
            int moveStatus = getSingleValue(value[5]);
            ppgMeasureData.setMoveStatus(moveStatus);
        }
        if (dataType == PPGMeasureData.MeasureData_PPGBP) {
            int stressValue = getSingleValue(value[6]);
            int sbpValue = getSingleValue(value[7]);
            int dbpValue = getSingleValue(value[8]);
            int progress = getSingleValue(value[9]);
            ppgMeasureData.setMeasureProgress(progress);
            ppgMeasureData.setSbpValue(sbpValue);
            ppgMeasureData.setDbpValue(dbpValue);
            ppgMeasureData.setStressValue(stressValue);
        }
        return ppgMeasureData;
    }

    /**
     * @param value
     * @return
     */
    public static SleepData getSleepData(byte[] value) {
        int valueLength=value.length;
        if (valueLength< 7) return null;
//        String date = "20" + bcd2String(value[1]) + "."
//                + bcd2String(value[2]) + "." + bcd2String(value[3]) + " "
//                + bcd2String(value[4]) + ":" + bcd2String(value[5]) + ":" + bcd2String(value[6]);
        String date = getDataFullDate(value,1);
        Log.i(TAG, "getSleepData: "+date+" "+ResolveUtil.byte2Hex(value));
        SleepData sleepData = new SleepData();
        int length = getSingleValue(value[7]);
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int dataPosition=8+i;
            if(dataPosition>=valueLength)return null;
            stringBuffer.append(getSingleValue(value[8 + i])).append(" ");
        }
        sleepData.setDate(date);
        sleepData.setSleepQuality(stringBuffer.toString().trim());
        return sleepData;
    }

    public static String getDataFullDate(byte[] value, int start) {
        Calendar calendar = Calendar.getInstance();
        int year = bcd2String(value[start++]);
        int month = bcd2String(value[start++]);
        int day = bcd2String(value[start++]);
        int hour = bcd2String(value[start++]);
        int minute = bcd2String(value[start++]);
        int second = bcd2String(value[start++]);
        calendar.set(Calendar.YEAR, year+2000);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, second);
        long current=System.currentTimeMillis();
        return calendar.getTimeInMillis()>current?"2000.01.01 00:00:00":DateUtils.getDefaultDate(calendar.getTime());
    }

    public static EcgMeasureResult getEcgData(byte[] value) {
        EcgMeasureResult ecgMeasureResult = new EcgMeasureResult();
        int length = value.length;
        Log.i(TAG, "getEcgData: " + length);
        byte[] data = new byte[length - 8];
        System.arraycopy(value, 8, data, 0, data.length);
        int id = getSingleValue(value[1]);
        int hrValue = getSingleValue(value[2]);
        int signal = getSingleValue(value[3]);
        int hrvValue = getSingleValue(value[5]);
        int moodValue = getSingleValue(value[6]);
        int brValue = getSingleValue(value[7]);
        ecgMeasureResult.setBreathValue(brValue);
        ecgMeasureResult.setId(id);
        ecgMeasureResult.setHrValue(hrValue);
        ecgMeasureResult.setHrvValue(hrvValue);
        ecgMeasureResult.setMoodValue(moodValue);
        ecgMeasureResult.setSignalQuality(signal);
        ecgMeasureResult.setEcgValue(data);
        return ecgMeasureResult;
    }

    public static float getBigDecimalData(float data, int newScale) {
        BigDecimal bigDecimal = new BigDecimal(String.valueOf(data));
        BigDecimal newBigDecimal = bigDecimal.setScale(newScale, RoundingMode.HALF_DOWN);
        return newBigDecimal.floatValue();
    }

    public static NumberFormat getNumberFormat(int max) {
        NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.ENGLISH);
        numberFormat.setMaximumFractionDigits(max);
        numberFormat.setGroupingUsed(false);
        return numberFormat;
    }

    public static int bcd2String(byte bytes) {
        StringBuffer temp = new StringBuffer();
        temp.append((byte) ((bytes & 0xf0) >>> 4));
        temp.append((byte) (bytes & 0x0f));
        return Integer.valueOf(temp.toString());
    }

    public static int getSingleValue(byte singleValue) {
        return getValue(singleValue, 0);
    }

    public static int getValue(byte b, int count) {
        return (int) ((b & 0xff) * Math.pow(256, count));
    }

    public static int getRangeValue(byte[] value, int start, int length) {
        int data = 0;
        for (int i = 0; i < length; i++) {
            data += getValue(value[start + i], i);
        }
        return data;
    }

    public static float getTempValue(byte[] value) {
        int tempHigh = getSingleValue(value[2]);
        int tempLow = getSingleValue(value[3]);
        String tempValue = tempHigh + "." + tempLow;
        return Float.valueOf(tempValue);
    }
}
